import * as d3 from "d3";
import * as DEFAULT from "@/utils/graph/default";

export function EventManager(ctx) {

  let context = ctx;

  // 事件管理对象
  let eventsList = initEventsList();

  function initEventsList() {
    if (!context.kgInfo.eventsList) {
      context.kgInfo.eventsList = {
        nodeHover:  { id:0, valid:true }, //鼠标划入划出节点边界显示
        linkHover:  { id:1, valid:true },//鼠标划入划出连接边界显示
        buttonHover:  { id:2, valid:true } , //鼠标划入按钮高亮
        dragNode: { id:3, valid:true }, //拖动节点
        switchBtnShow: { id:4, valid:true }, //左单击节点展示按钮组
        selectNode: { id:5, valid:true }, //双击选择节点
        viewNode: { id:6, valid:true }, //展示鼠标划入节点信息
        relatedNode: { id:7, valid:true }, //展示鼠标划入相关节点、连接信息
        btnDeleteNode: { id:8, valid:true } //用按钮组删除节点
      }
    }
    return context.kgInfo.eventsList;
  }

  /**---------------------------------------------------------------------------
   * 改变某些方法的有效性
   * @param changes 变化属性数组
   */
  this.changeEvents = function(changes) {
    if (!Array.isArray(changes)) return;
    changes.forEach(change => {
      if (
        typeof change == "object" &&
        change.eventName !== undefined &&
        eventsList[change.eventName] !== undefined &&
        change.valid !== undefined &&
        typeof change.valid == "boolean"
      ) {
        eventsList[change.eventName] = change.valid;
      }
    });
  };

  /**---------------------------------------------------------------------------
   * 初始化所有默认事件
   */
  this.initDefaultEvent = function() {
    this.initNodeEvent();
    this.initLinkEvent();
    this.initButtonEvent();
  }

  /**---------------------------------------------------------------------------
   * 初始化所有节点默认事件
   * @param _this
   */
  this.initNodeEvent = function() {
    let nodeEnter = context.qaGraphNode.selectAll("circle");
    let nodetextEnter = context.qaGraphNodeText.selectAll("text");

    if(eventsList.relatedNode.valid)
      this.openRelatedNodeEvent(nodeEnter);

    if(eventsList.viewNode.valid)
      this.openViewNodeEvent(nodeEnter);

    if(eventsList.selectNode.valid){
      addNodeEvent("dblclick." + eventsList.selectNode.id, function(node) {
        if(context.selectedNode && node.uuid == context.selectedNode.uuid) context.elementEditor.giveUpNode();
        else context.elementEditor.focusNode(node);
        event.stopPropagation();
      },nodeEnter);
    }

    if(eventsList.nodeHover.valid){
      addNodeEvent("mouseenter." + eventsList.nodeHover.id,function() {
        d3.select(this)
          .style("stroke-width", DEFAULT.NODE_STROKE_WIDTH_BOLD)
          .style("cursor","pointer");
      },nodeEnter)
      addNodeEvent("mouseleave." + eventsList.nodeHover.id,function() {
        d3.select(this)
          .style("stroke-width", DEFAULT.NODE_STROKE_WIDTH)
          .style("cursor","normal");
      },nodeEnter)
    }

    if(eventsList.dragNode.valid){
      nodeEnter.call(
        d3
          .drag()
          .on("start." + eventsList.dragNode.id, context.simulation.dragStarted())
          .on("drag." + eventsList.dragNode.id, context.simulation.dragged())
          .on("end." + eventsList.dragNode.id, context.simulation.dragEnded())
      );
      nodetextEnter.call(
        d3
          .drag()
          .on("start." + eventsList.dragNode.id, context.simulation.dragStarted())
          .on("drag." + eventsList.dragNode.id, context.simulation.dragged())
          .on("end." + eventsList.dragNode.id, context.simulation.dragEnded())
      );
    }

  }

  /**---------------------------------------------------------------------------
   * 初始化所有连接默认事件
   */
  this.initLinkEvent = function() {
    let linkEnter = context.qaGraphLink.selectAll("path");

    if(eventsList.linkHover.valid){
      addLinkEvent("mouseover." + eventsList.linkHover.id,function() {
        d3.select(this)
          .style("stroke-width", DEFAULT.LINK_STROKE_WIDTH_BOLD)
          .style("cursor","pointer");
      },linkEnter)
      addLinkEvent("mouseleave." + eventsList.linkHover.id,function() {
        d3.select(this)
          .style("stroke-width", DEFAULT.LINK_STROKE_WIDTH)
          .style("cursor","normal");
      },linkEnter)
    }

  }

  /**---------------------------------------------------------------------------
   * 初始化按钮组默认事件
   */
  this.initButtonEvent = function() {
    let codeName = context.buttonGroupManager.codeName;

    if(eventsList.buttonHover.valid){
      context.buttonGroupManager.toolbarData.forEach(function(data) {
        (function(code){
          addButtonEvent("mouseenter." + eventsList.buttonHover.id + code,function(d) {
            d3.select(this).style("opacity",DEFAULT.BTN_OPACITY_HOVER);
            console.log(d.data.code)
          },code);
          addButtonEvent("mouseleave." + eventsList.buttonHover.id + code,function() {
            d3.select(this).style("opacity",DEFAULT.BTN_OPACITY);
          },code);
        })(data.code);
      })
    }

    if(eventsList.btnDeleteNode.valid){
      addButtonEvent("click." + eventsList.btnDeleteNode.id,function() {
        context.vueComponent.deleteNodeByBtn();
      },codeName.delete);
    }

  }

  /**---------------------------------------------------------------------------
   * 开启关闭显示相关节点与连接方法
   * （鼠标悬浮在某个节点会展示与其相关的所有节点与连接 而隐藏其他节点与连接）
   */
  this.openRelatedNodeEvent = function(nodes) {
    eventsList.relatedNode.valid = true;
    addNodeEvent("mouseenter." + eventsList.relatedNode.id,
      context.elementEditor.showNodeRelated,nodes);
    addNodeEvent("mouseleave." + eventsList.relatedNode.id,
      context.elementEditor.showAll,nodes);
  }
  this.closeRelatedNodeEvent = function(nodes) {
    eventsList.relatedNode.valid = false;
    addNodeEvent("mouseenter." + eventsList.relatedNode.id,null,nodes);
    addNodeEvent("mouseleave." + eventsList.relatedNode.id,null,nodes);
  }

  /**---------------------------------------------------------------------------
   * 开启、关闭显示当前鼠标所在节点信息相关方法
   */
  this.openViewNodeEvent = function(nodes) {
    eventsList.viewNode.valid = true;
    addNodeEvent("mouseenter." + eventsList.viewNode.id,function(d) {
      let viewNode = context.viewNode;
      viewNode.uuid = d.uuid;
      viewNode.uri = d.uri;
      viewNode.label = d.label;
      viewNode.type = d.type;
      viewNode.x = d.x;
      viewNode.y = d.y;
      viewNode.valid = true;
    },nodes);
    addNodeEvent("mouseleave." + eventsList.viewNode.id,function() {
      let viewNode = context.viewNode;
      viewNode.valid = false;
    },nodes);
  }
  this.closeViewNodeEvent = function(nodes) {
    eventsList.viewNode.valid = false;
    addNodeEvent("mouseenter." + eventsList.viewNode.id,null,nodes);
    addNodeEvent("mouseleave." + eventsList.viewNode.id,null,nodes);
  }

  /**---------------------------------------------------------------------------
   * 给所有节点添加事件
   * @param eventName
   * @param callback
   * @param nodes
   */
  function addNodeEvent(eventName, callback, nodes) {
    if(!nodes){
      nodes = d3.selectAll('circle');
    }
    nodes.on(eventName,callback);
  }

  /**---------------------------------------------------------------------------
   * 给所有连接添加事件
   * @param eventName
   * @param callback
   * @param links
   */
  function addLinkEvent(eventName, callback, links) {
    if(!links){
      links = d3.selectAll('path');
    }
    links.on(eventName,callback);
  }

  /**---------------------------------------------------------------------------
   * 为某一种按钮添加事件
   * @param eventName
   * @param callback
   * @param code 按钮标识
   */
  //
  function addButtonEvent(eventName,callback,code) {
    context.buttonGroupManager.toolbarData.forEach(function(m) {
      if(m.code == code){
        let btnClass = ".action_" + code;
        d3.selectAll(btnClass).select("path").on(eventName,(function() {
          return callback;
        })());
      }
    });
  }

}
